package com.youlu.campus.web.membership.service.impl;

import com.alibaba.fastjson.JSON;
import com.youlu.campus.base.exception.BusinessException;
import com.youlu.campus.base.order.GoodsInfo;
import com.youlu.campus.base.order.enums.OrderPayTypeEnum;
import com.youlu.campus.entity.MemberShipInfo;
import com.youlu.campus.entity.UserMemberShipInfo;
import com.youlu.campus.entity.UserPO;
import com.youlu.campus.entity.VO.PlaceOrderReq;
import com.youlu.campus.entity.VO.req.MemberShipOrderVO;
import com.youlu.campus.entity.WechatPayCache;
import com.youlu.campus.service.wechatpay.WechatPayCacheService;
import com.youlu.campus.web.common.base.RequestContext;
import com.youlu.campus.web.membership.service.UserMemberShipInfoService;
import com.youlu.campus.web.order.entity.OrderPO;
import com.youlu.campus.web.order.service.OrderBaseService;
import com.yuelin.infrastructure.quantum.common.QResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;


@Slf4j
@Service
public class UserMemberShipInfoServiceImpl extends OrderBaseService implements UserMemberShipInfoService {
    @Autowired
    private WechatPayCacheService wechatPayCacheService;

    @Override
    public MemberShipInfo getUserMemberShipInfo(String userId) {
        log.info(":>>> 获取用户会员卡信息:{}", userId);
        Query query = new Query().addCriteria(Criteria.where("userId").is(userId).and("expired").ne(Boolean.TRUE));
        UserMemberShipInfo userMemberShipInfo = mongoTemplate.findOne(query, UserMemberShipInfo.class);

        Query queryAct = new Query().addCriteria(Criteria.where("status").is(1));
        MemberShipInfo memberShipInfo = mongoTemplate.findOne(queryAct, MemberShipInfo.class);
        if (Objects.isNull(memberShipInfo)) {
            log.error(":>>> 无可用会员卡信息,请联系客服");
            throw new BusinessException("无可用会员卡信息,请联系客服");

        }
        if (Objects.isNull(userMemberShipInfo) || Objects.isNull(userMemberShipInfo.getMemberShipInfoId())) {
            log.info(":>>> 用户会员卡信息为空");
            return memberShipInfo;
        } else {
            // 已经发布
            Query queryAct2 = new Query().addCriteria(Criteria.where("id").is(userMemberShipInfo.getMemberShipInfoId()));
            MemberShipInfo memberShipInfo2 = mongoTemplate.findOne(queryAct2, MemberShipInfo.class);
            log.info(":>>> 用户:{},会员卡信息:{}", userId, JSON.toJSONString(memberShipInfo2));
            return memberShipInfo2;
        }

    }

    @Override
    public void memberShipPayOrder(MemberShipOrderVO req) {
        log.info(":>>> 开始会员卡购买下单;{}", JSON.toJSONString(req));
        if (Objects.isNull(req)) {
            log.error(":>>> 购买会员信息错误:{}", JSON.toJSONString(req));
            throw new BusinessException("获取用户会员卡信息错误:用户ID为空");
        }
    }

    /**
     * 下单
     *
     * @return
     */
    @Override
    public Map<String, String> placeOrder(PlaceOrderReq req) {
        log.info(":>>> 会员卡下单 userId {} req {}", RequestContext.getUserId(), req);
        if (StringUtils.isBlank(req.getGoodsCode())) {
            log.error(":>>> 商品编码为空");
            throw new BusinessException("商品编码不能为空~");
        }
        if (super.resubmit(3L, RequestContext.getUserId(), req)) {
            log.info(":>>> 有已经待支付的订单,请不要重复支付");
            throw new BusinessException("请勿重复发起支付~");
        }

        UserPO user = RequestContext.getCurUser();
        //获取订单信息
        OrderPO orderPO = this.saveMemberShipdOrder(RequestContext.getCurUser(), req);
        Map<String, String> result = new HashMap<>();
        //获取预支付参数
        QResult<Map<String, String>> uniOrderResult = super.getUniOrderResult(orderPO);
        log.info(":>>> 获取微信预支付参数结果为:{}", JSON.toJSONString(uniOrderResult));
        // 支付成功
        if (uniOrderResult.code == 0) {
            result = uniOrderResult.data;
            WechatPayCache cache = new WechatPayCache();
            cache.setOrderNo(orderPO.getOrderNo());
            cache.setType("oid");
            cache.setBizType("membership");
            cache.setCreatedTime(new Date());
            wechatPayCacheService.create(cache);
            log.info("placeOrder applyReq {} result {}", req, result);
        } else {
            log.info("placeOrder applyReq {} error msg {}", req, uniOrderResult.msg);
        }
        return result;
    }

    @Override
    public boolean handlePayNotify(OrderPO orderPO) {
        log.info(":>>> 处理支付通知信息:{}", JSON.toJSONString(orderPO));

        return false;
    }

    /**
     * 保存会员卡订单
     *
     * @param user
     * @param req
     * @return
     */
    protected OrderPO saveMemberShipdOrder(UserPO user, PlaceOrderReq req) {
        log.info("saveOrder userId {} applyReq {}", user.getId(), req);
        UserMemberShipInfo userMemberShipInfo = new UserMemberShipInfo();
        MemberShipInfo memberShipInfo = this.getUserMemberShipInfo(req.getMemberShipInfo().getId());
        userMemberShipInfo.setUserId(user.getId());
        userMemberShipInfo.setMemberShipInfoId(memberShipInfo.getId());
        // goodsCode对应证书编码
        String orderNo = super.generateOrderNo("20");
        userMemberShipInfo.setOrderNo(orderNo);
        // 待支付
        userMemberShipInfo.setStatus(0);
        userMemberShipInfo.setName(user.getName());
        userMemberShipInfo.setMobile(user.getMobile());
        userMemberShipInfo.setPayFee(memberShipInfo.getPrice());
        userMemberShipInfo.setExpired(false);
        userMemberShipInfo = mongoTemplate.insert(userMemberShipInfo);
        log.info(":>>> 创建会员卡信息结果:{}", JSON.toJSONString(userMemberShipInfo));


        OrderPO orderPO = new OrderPO();
        // goodsCode对应证书编码
        orderPO.setOrderNo(orderNo);
        orderPO.setSource(req.getSource());
        orderPO.setPayType(OrderPayTypeEnum.WX.getCode());
        GoodsInfo goods = new GoodsInfo();
        goods.setGoodsName(memberShipInfo.getName());
        orderPO.setGoods(goods);
        orderPO.setPayPrice(memberShipInfo.getPrice());
        orderPO.setTotalPrice(memberShipInfo.getPrice());
        orderPO.setClientIp(req.getClientIp());
        return orderPO;
    }
}
